CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
project(RTT307 VERSION 0.1 LANGUAGES C)
SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_PROCESSOR "arm")

SET(CMAKE_C_STANDARD 11)
SET(CMAKE_CXX_STANDARD 14)

SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
enable_language(ASM)

if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
    SET(TOOLCHAIN_PATH "/home/charx/software/arm-gnu-none-eabi/bin/")
    SET(TOOLCHAIN_PREFIX "arm-none-eabi-")
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "risc-v")
    SET(TOOLCHAIN_PATH "/home/charx/software/MounRiver_Studio/toolchain/RISC-V\ Embedded\ GCC/bin")
    SET(TOOLCHAIN_PREFIX "riscv-none-embed-")
endif()

SET(CMAKE_C_COMPILER "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}gcc")
SET(CMAKE_CXX_COMPILER "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}g++")
SET(CMAKE_ASM_COMPILER "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}as")
SET(CMAKE_AR "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}ar")
SET(CMAKE_LINKER "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}gcc")
SET(CMAKE_SIZE "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}size")
SET(CMAKE_OBJCOPY "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}objcopy")
SET(CMAKE_OBJDUMP "${TOOLCHAIN_PATH}/${TOOLCHAIN_PREFIX}objdump")

SET(CMAKE_EXPORT_COMPILE_COMMANDS ON)

SET(DEBUG_FLAGS -g)

if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
    SET(ARCH -mcpu=cortex-m0)
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "risc-v")
    SET(ARCH -march=riscv)
endif()

SET(C_COMPILE_FLAGS "${ARCH} -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common -Wunused -Wuninitialized ${DEBUG_FLAGS}")

SET(ASM_COMPILE_FLAGS "${ARCH}")

# 选择链接脚本地址:
SET(LINKER_PATH "${CMAKE_SOURCE_DIR}/Driver/Flash.ld")
SET(LD_FLAGS "-march=${ARCH} -msmall-data-limit=8 -msave-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common -Wunused -Wuninitialized  -T${DEBUG_FLAGS} -nostartfiles -Xlinker --gc-sections -Wl,-Map,${PROJECT_NAME}.map --specs=nano.specs --specs=nosys.specs")

function(append_asm_sources dir variable)
    # 使用GLOB命令查找所有.s文件，不递归
    file(GLOB new_sources1 "${dir}/*.s")
    foreach(ASM_SRC_FILE ${new_sources1})
        set_source_files_properties(${ASM_SRC_FILE} PROPERTIES COMPILE_FLAGS ${ASM_COMPILE_FLAGS})
    endforeach()
    message(STATUS "new1:${new_sources1}")

    # 使用GLOB命令查找所有.S文件，不递归
    file(GLOB new_sources2 "${dir}/*.S")
    foreach(ASM_SRC_FILE ${new_sources2})
        set_source_files_properties(${ASM_SRC_FILE} PROPERTIES COMPILE_FLAGS ${ASM_COMPILE_FLAGS})
    endforeach()
    message(STATUS "new2:${new_sources2}")
    set(${variable} ${${variable}} ${new_sources1} ${new_sources2} PARENT_SCOPE)
endfunction()

function(append_asm_sources_single asm_file variable)
    # 使用GLOB命令查找所有.s文件，不递归
    set_source_files_properties(${asm_file} PROPERTIES COMPILE_FLAGS ${ASM_COMPILE_FLAGS})
    set(${variable} ${${variable}} ${asm_file} PARENT_SCOPE)
endfunction()


function(append_c_sources dir variable)
    # 使用GLOB命令查找所有.C文件，不递归
    file(GLOB new_sources1 "${dir}/*.c")
    foreach(SRC_FILE ${new_sources1})
        set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_FLAGS ${C_COMPILE_FLAGS})
    endforeach()
    message(STATUS "new1:${new_sources1}")
    message(STATUS "C:${${variable}}")
	
    # 使用GLOB命令查找所有.C文件，不递归
    file(GLOB new_sources2 "${dir}/*.C")
    foreach(SRC_FILE ${new_sources2})
        set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_FLAGS ${C_COMPILE_FLAGS})
    endforeach()
    message(STATUS "new2:${new_sources2}")
    # 将新找到的源文件追加到指定变量中 PARENT_SCOPE 表示修改父目录的变量
    set(${variable} ${${variable}} ${new_sources1} ${new_sources2} PARENT_SCOPE)
endfunction()

# 添加单个.c文件
function(append_c_sources_single c_file variable)
    set_source_files_properties(${c_file} PROPERTIES COMPILE_FLAGS ${C_COMPILE_FLAGS})
    set(${variable} ${${variable}} ${c_file} PARENT_SCOPE)
endfunction(append_c_sources_single c_file variable)

# 递归添加.c/.C文件
function(append_c_sources dir variable)
    # 使用GLOB命令查找所有.C文件，递归
    file(GLOB_RECURSE new_sources1 "${dir}/*.c")
    foreach(SRC_FILE ${new_sources1})
        set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_FLAGS ${C_COMPILE_FLAGS})
    endforeach()
    message(STATUS "new1:${new_sources1}")
    message(STATUS "C:${${variable}}")
	
    # 使用GLOB命令查找所有.C文件，递归
    file(GLOB_RECURSE new_sources2 "${dir}/*.C")
    foreach(SRC_FILE ${new_sources2})
        set_source_files_properties(${SRC_FILE} PROPERTIES COMPILE_FLAGS ${C_COMPILE_FLAGS})
    endforeach()
    message(STATUS "new2:${new_sources2}")
    # 将新找到的源文件追加到指定变量中 PARENT_SCOPE 表示修改父目录的变量
    set(${variable} ${${variable}} ${new_sources1} ${new_sources2} PARENT_SCOPE)
endfunction()

# ---------------------------------------------------------------- Set sources file variable -------------------------------------------------
SET(CC_SOURCES "")
SET(ASM_SOURCES "")
# --------------------------------------------------------------------------------------------------------------------------------------------

# ---------------------------------------------------------------- main processor code -------------------------------------------------------

# ---------------------------------------------------------------- Add includes dir ----------------------------------------------------------
include_directories(./Driver/Libraries/inc)
include_directories(./MOTOR)
include_directories(./User)
include_directories(./CMSIS)
# --------------------------------------------------------------------------------------------------------------------------------------------

# ---------------------------------------------------------------- Add C source files --------------------------------------------------------
append_c_sources("./Driver/Libraries/src" CC_SOURCES)
append_c_sources("./MOTOR" CC_SOURCES)
append_c_sources("./User" CC_SOURCES)

message(STATUS "C_SRC:${CC_SOURCES}")
# --------------------------------------------------------------------------------------------------------------------------------------------

# ---------------------------------------------------------------- Add ASM source files ------------------------------------------------------
append_asm_sources_single("./User/startup_gcc.s" ASM_SOURCES)
message(STATUS "ASM_SRC:${ASM_SOURCES}")
# --------------------------------------------------------------------------------------------------------------------------------------------

add_executable(${PROJECT_NAME}.elf ${CC_SOURCES} ${ASM_SOURCES})

target_link_options(
    ${PROJECT_NAME}.elf PRIVATE
    "${ARCH}"
    "-Os"
    "-fmessage-length=0"
    "-fsigned-char"
    "-ffunction-sections"
    "-fdata-sections"
    "-fno-common"
    "-Wunused"
    "-Wuninitialized"
    ""
    "${DEBUG}"
    "-T${LINKER_PATH}"
    "-Xlinker"
    "--gc-sections"
    "-Wl,-Map,${PROJECT_NAME}.map"
    "--specs=nano.specs"
    "--specs=nosys.specs"
)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E echo "Build succeed!Generating hex and bin"
    COMMAND ${CMAKE_OBJCOPY} -Oihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
    COMMAND ${CMAKE_SIZE} ${PROJECT_NAME}.elf
)
